use std::{
    cell::RefCell,
    path::{Path, PathBuf},
    rc::Rc,
};

use crate::{math::Vector2u, function::utils::io::AliceUtils};

static CONFIG_DIR:&'static str = "config";

static CONFIG_FILENAME: &'static str = "config.json";

#[derive(Clone)]
pub struct AliceConfig(Rc<RefCell<AliceConfigImpl>>);

impl std::ops::Deref for AliceConfig {
    type Target = Rc<RefCell<AliceConfigImpl>>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl AliceConfig {
    pub fn new() -> Self {
        Self(Rc::new(RefCell::new(AliceConfigImpl::new())))
    }
}

impl AliceConfig {
    pub fn get_window_size(&self) -> Vector2u {
        self.0.borrow().window_size
    }

    pub fn get_screen_size(&self) -> Vector2u {
        self.0.borrow().screen_size
    }

    pub fn set_window_size(&mut self, size: Vector2u) {
        self.0.borrow_mut().window_size = size;
    }

    pub fn set_screen_size(&mut self, size: Vector2u) {
        self.0.borrow_mut().screen_size = size;
    }

    pub fn get_scale_factory(&self) -> f32 {
        self.0.borrow().scale_factory
    }

    pub fn set_scale_factory(&mut self, scale_factory: f32) {
        self.0.borrow_mut().scale_factory = scale_factory;
    }

    pub fn get_project_name(&self) -> String {
        self.0.borrow().project_name.to_owned()
    }

    pub fn set_project_name(&mut self, name: &str) {
        self.0.borrow_mut().project_name = name.to_owned()
    }

    pub fn get_project_root(&self) -> std::path::PathBuf {
        self.0.borrow().project_path.clone()
    }

    pub fn set_project_root(&mut self, root: &str) {
        self.0.borrow_mut().project_path = Path::new(root).to_path_buf()
    }
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct AliceConfigImpl {
    /// 项目名称
    project_name: String,
    /// 项目根路径
    project_path: PathBuf,
    /// 默认窗口大小
    window_size: Vector2u,
    /// 显示区域大小
    screen_size: Vector2u,
    ///
    scale_factory:f32
}

impl Default for AliceConfigImpl {
    fn default() -> Self {
        Self {
            project_name: "Alice Engine(webgpu)".to_string(),
            project_path: std::env::current_dir().unwrap(),
            window_size: Vector2u::new(1280, 768),
            screen_size: Vector2u::new(1280, 768),
            scale_factory:1.0
        }
    }
}

impl AliceConfigImpl {
    pub fn new() -> Self {
        match std::env::current_dir() {
            Ok(dir) => {
            
                Self::read_config(dir.join(CONFIG_DIR))
            }
            Err(_e) => {
                panic!("解析项目根路径失败!")
            }
        }
    }

    pub fn read_config(dir: PathBuf) -> Self {
        let write_path = dir.clone();

        match AliceUtils::read_text_file(dir,"config.json") {
            Ok(config) => match serde_json::from_str(&config) {
                Ok(config) => {
                    let mut config:AliceConfigImpl = config;
                    if config.screen_size.x > config.window_size.x || config.screen_size.y  > config.window_size.y  {
                        config.screen_size = config.window_size;
                    }
                    config
                },
                Err(_) => {
                    println!("配置文件损坏！将使用默认配置");
                    let config = Self::default();
                  
                    let config_json = serde_json::to_string(&config).unwrap();
            
                    AliceUtils::write_text_file(write_path, CONFIG_FILENAME, &config_json).unwrap();
            
                    config
                }
            },
            Err(_) => {
                println!("读取配置文件失败！将使用默认配置");
                let config = Self::default();
              
                let config_json = serde_json::to_string(&config).unwrap();
        
                AliceUtils::write_text_file(write_path, CONFIG_FILENAME, &config_json).unwrap();
        
                config
            }
        }
     
       
    }
}
